package com.spring.cloud.study.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.spring.cloud.study.entity.SysRole;
import com.spring.cloud.study.entity.SysUser;
import com.spring.cloud.study.repository.SysUserRepository;
import com.spring.cloud.study.service.SysRoleService;
import com.spring.cloud.study.service.SysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.util.*;

/**
 * Created by SuperS on 2017/9/25.
 *
 * @author SuperS
 */
@Service
public class SysUserServiceImpl implements SysUserService {
    private final Logger log = LoggerFactory.getLogger(getClass());

    private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    @Autowired
    private SysUserRepository userRepository;

    @Autowired
    private SysRoleService sysRoleService;

    @Override
    public SysUser getUserDetail(String username) {
        return userRepository.findByUsername(username);
    }

    @Override
    public void save(SysUser user) {
        SysUser existing = userRepository.findByUsername(user.getUsername());
        if(existing != null){
            log.error("用户名称已经存在: {}", user.getUsername());
            return;
        }

        if(user.getRoleIds().size() > 0){
            List<SysRole> sysRoleList = sysRoleService.findBatch(user.getRoleIds());
            if(sysRoleList != null && sysRoleList.size() > 0){
                user.setRoles(new HashSet<>(sysRoleList));
            }
        }

        String hash = encoder.encode(user.getPassword());
        user.setPassword(hash);
        userRepository.save(user);
        log.info("new user has been created: {}", user.getUsername());
    }

    @Override
    public void saveBatch(Collection<SysUser> collection) {

        collection.forEach(sysUser -> save(sysUser));
    }

    @Override
    @Transactional
    public Page<SysUser> findPage(Map<String,Object> params) {
        String filter = params.get("filter").toString();
        JSONObject jsonObject = JSONObject.parseObject(filter);
        Sort sort = new Sort(Sort.Direction.ASC, "username");
        Pageable pageable = new PageRequest(Integer.parseInt(params.get("page").toString())-1, Integer.parseInt(params.get("limit").toString()), sort);
        Specification specification = new Specification<SysUser>() {
            @Override
            public Predicate toPredicate(Root<SysUser> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if(jsonObject.get("username") != null && !jsonObject.get("username").equals("")){
                    predicates.add(criteriaBuilder.like(root.get("username"),"%"+jsonObject.get("username").toString()+"%"));
                }
                if(jsonObject.get("displayName") != null && !jsonObject.get("displayName").equals("")){
                    predicates.add(criteriaBuilder.like(root.get("displayName"),"%"+jsonObject.get("displayName").toString()+"%"));
                }

                if(jsonObject.get("phone") != null && !jsonObject.get("phone").equals("")){
                    predicates.add(criteriaBuilder.like(root.get("phone"),"%"+jsonObject.get("phone").toString()+"%"));
                }


                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        Page<SysUser> page = userRepository.findAll(specification,pageable);
        return page;
    }

    @Override
    public List<SysUser> findBatch(Object[] objects) {
        return null;
    }

    @Override
    public List<SysUser> findBatch(Collection<Integer> collection) {
        return null;
    }

    @Override
    public SysUser findById(int id) {
        return userRepository.findOne(id);
    }

    @Override
    public List<SysUser> findAll() {
        return null;
    }

    @Override
    public void update(SysUser user) {
        SysUser existing = userRepository.findOne(user.getId());
        if(existing != null){
            if(existing.getId() != user.getId()){
                log.error("用户名称已经存在: {}", user.getUsername());
                return;
            }
        }

        if(user.getRoleIds().size() > 0){
            List<SysRole> sysRoleList = sysRoleService.findBatch(user.getRoleIds());
            if(sysRoleList != null && sysRoleList.size() > 0){
                user.setRoles(new HashSet<>(sysRoleList));
            }
        }

        String passwordNew = user.getPassword();
        if(passwordNew != null && !passwordNew.trim() .equals("")){
            String hash = encoder.encode(passwordNew);
            user.setPassword(hash);
        }else{
            user.setPassword(existing.getPassword());
        }
        userRepository.save(user);
        log.info("new user has been created: {}", user.getUsername());
    }

    @Override
    public int delete(SysUser sysUser) {

        return 0;
    }

    @Override
    public void delete(int id) {
        userRepository.delete(id);
    }

    @Override
    public int deleteBatch(Object[] objects) {
        return 0;
    }

    @Override
    public void deleteBatch(Collection collection) {

    }


}
